<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>
    <script>
        // 每一个链都是一个data用来存值，一个next用来指向下一个链从而形成一个链表
        class Node {
            constructor(data) {
                this.data = data;
                this.next = null;
            }
        }

        // 我们用的是链表，所以需要根据链再封装一个链表类
        class linkedList {
            constructor() {
                this.head = null;
                this.count = 0;
            }

            // push方法从链表的最后面进行插入
            push(data) {
                let node = new Node(data);

                if(this.head==null){
                    this.head = node;
                }
                else{
                    // 用一个current变量来保存下head，用来从头开始
                    let current = this.head;
                    // 只要current还有next，那就代表还没到尾部
                    while(current.next){
                        current = current.next;
                    }
                    // 循环结束，则代表已经到了尾部，那这个时候就可以进行插入操作了
                    current.next = node;
                }
                //别忘了给长度++
                this.count++;
            }

            // 指定位置删除
            removeAt(index) {
                // 如果index小于0或者大于等于长度了，那就是不合法的，直接return;
                if (index < 0 || index >= this.count) {
                    return;
                }

                let current = this.getNodeAt(index);
                if (index == 0) {
                    this.head = this.head.next;
                }
                else{
                    this.getNodeAt(index-1).next = this.getNodeAt(index).next;
                }
                this.count--;
                return current.data;
            }

            getNodeAt(index){
                if(index<0 || index>=this.count){
                    return ;
                }

                let node = this.head;
                for(let i = 0;i<index;i++){
                    node = node.next;
                }
                return node;
            }

            // 根据数据的值进行删除
            remove(data){
                let index = this.indexOf(data);
                return this.removeAt(index);
            }

            // 根据传入的数据和索引值进行插入操作
            insert(data,index){
                if(index<0||index>this.count){
                    return ;
                }

                let node = new Node(data);
                if(index==0){
                    node.next = this.head;
                    this.head = node;
                }
                else{
                    let previous = this.getNodeAt(index-1);
                    let current = this.getNodeAt(index);
                    previous.next = node;
                    node.next = current;
                }
                this.count++;
                return node; 
            }

            // 根据值搜寻第一个目标的下标位置
            indexOf(data){
                let node = this.head;
                for(let i = 0;i<this.count;i++){
                    if(node.data == data){
                        return i;
                    }
                    node = node.next;
                }
                return -1;
            }

            // 对比方法
            equal(a,b){
                return JSON.stringify(a) === JSON.stringify(b);
            }

            size(){
                return this.count;
            }

            isEmpty(){
                return this.size()===0
            }

            getHead(){
                return this.head;
            }
        }

        let ll = new linkedList();
    </script>
</body>

</html>